package com.zouxw.utils.json.utils;

import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 树节点展开优化工具类
 * 提供异步和批量展开功能，提升大JSON文件的性能
 * 
 * @author zouxw
 * @version 1.0
 */
public class TreeExpansionUtil {
    
    // ==================== 配置常量 ====================
    /** 批量展开的节点数量阈值 */
    private static final int BATCH_SIZE = 50;
    
    /** 异步展开的节点数量阈值 */
    private static final int ASYNC_THRESHOLD = 100;
    
    /** 线程池 */
    private static final ExecutorService executor = Executors.newSingleThreadExecutor();
    
    // ==================== 私有构造函数 ====================
    /**
     * 私有构造函数，防止实例化
     */
    private TreeExpansionUtil() {
        throw new UnsupportedOperationException("树展开工具类不能被实例化");
    }
    
    // ==================== 公共方法 ====================
    
    /**
     * 智能展开所有节点
     * 根据节点数量自动选择同步或异步展开
     * 
     * @param tree 树组件
     */
    public static void expandAllNodes(JTree tree) {
        if (tree == null || tree.getModel() == null) {
            return;
        }
        
        int totalNodes = countNodes(tree);
        
        if (totalNodes < ASYNC_THRESHOLD) {
            // 节点数量较少，使用同步展开
            expandAllNodesSync(tree);
        } else {
            // 节点数量较多，使用异步展开
            expandAllNodesAsync(tree);
        }
    }
    
    /**
     * 同步展开所有节点
     * 
     * @param tree 树组件
     */
    public static void expandAllNodesSync(JTree tree) {
        if (tree == null || tree.getModel() == null) {
            return;
        }
        
        // 使用批量展开优化性能
        expandAllNodesBatch(tree, 0, tree.getRowCount());
    }
    
    /**
     * 异步展开所有节点
     * 
     * @param tree 树组件
     */
    public static void expandAllNodesAsync(JTree tree) {
        if (tree == null || tree.getModel() == null) {
            return;
        }
        
        CompletableFuture.runAsync(() -> {
            try {
                expandAllNodesBatch(tree, 0, tree.getRowCount());
            } catch (Exception e) {
                System.err.println("异步展开节点时出错: " + e.getMessage());
            }
        }, executor);
    }
    
    /**
     * 展开到指定深度
     * 
     * @param tree 树组件
     * @param maxDepth 最大深度
     */
    public static void expandToDepth(JTree tree, int maxDepth) {
        if (tree == null || tree.getModel() == null || maxDepth < 0) {
            return;
        }
        
        expandToDepthRecursive(tree, tree.getPathForRow(0), 0, maxDepth);
    }
    
    /**
     * 展开指定路径的节点
     * 
     * @param tree 树组件
     * @param path 路径
     */
    public static void expandPath(JTree tree, TreePath path) {
        if (tree == null || path == null) {
            return;
        }
        
        tree.expandPath(path);
        tree.scrollPathToVisible(path);
    }
    
    /**
     * 折叠所有节点
     * 
     * @param tree 树组件
     */
    public static void collapseAllNodes(JTree tree) {
        if (tree == null || tree.getModel() == null) {
            return;
        }
        
        // 从后往前折叠，避免索引变化问题
        for (int i = tree.getRowCount() - 1; i >= 0; i--) {
            tree.collapseRow(i);
        }
    }
    
    /**
     * 获取树的统计信息
     * 
     * @param tree 树组件
     * @return 统计信息
     */
    public static TreeStatistics getTreeStatistics(JTree tree) {
        if (tree == null || tree.getModel() == null) {
            return new TreeStatistics();
        }
        
        TreeStatistics stats = new TreeStatistics();
        countNodesRecursive(tree, tree.getPathForRow(0), stats);
        return stats;
    }
    
    // ==================== 私有辅助方法 ====================
    
    /**
     * 批量展开节点
     * 
     * @param tree 树组件
     * @param startIndex 开始索引
     * @param endIndex 结束索引
     */
    private static void expandAllNodesBatch(JTree tree, int startIndex, int endIndex) {
        int currentRowCount = tree.getRowCount();
        
        // 批量展开节点
        for (int i = startIndex; i < endIndex && i < currentRowCount; i++) {
            tree.expandRow(i);
            
            // 每展开BATCH_SIZE个节点后，更新一次UI
            if ((i - startIndex + 1) % BATCH_SIZE == 0) {
                SwingUtilities.invokeLater(() -> {
                    // 更新UI
                });
                
                // 短暂休眠，避免阻塞UI线程
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
        
        // 如果展开后有新节点，递归展开
        if (tree.getRowCount() != currentRowCount) {
            expandAllNodesBatch(tree, currentRowCount, tree.getRowCount());
        }
    }
    
    /**
     * 递归展开到指定深度
     * 
     * @param tree 树组件
     * @param path 当前路径
     * @param currentDepth 当前深度
     * @param maxDepth 最大深度
     */
    private static void expandToDepthRecursive(JTree tree, TreePath path, int currentDepth, int maxDepth) {
        if (path == null || currentDepth >= maxDepth) {
            return;
        }
        
        tree.expandPath(path);
        
        // 获取子节点并递归展开
        Object lastComponent = path.getLastPathComponent();
        if (lastComponent instanceof javax.swing.tree.TreeNode) {
            javax.swing.tree.TreeNode node = (javax.swing.tree.TreeNode) lastComponent;
            for (int i = 0; i < node.getChildCount(); i++) {
                TreePath childPath = path.pathByAddingChild(node.getChildAt(i));
                expandToDepthRecursive(tree, childPath, currentDepth + 1, maxDepth);
            }
        }
    }
    
    /**
     * 计算节点总数
     * 
     * @param tree 树组件
     * @return 节点总数
     */
    private static int countNodes(JTree tree) {
        TreeStatistics stats = new TreeStatistics();
        countNodesRecursive(tree, tree.getPathForRow(0), stats);
        return stats.getTotalNodes();
    }
    
    /**
     * 递归计算节点数量
     * 
     * @param tree 树组件
     * @param path 当前路径
     * @param stats 统计信息
     */
    private static void countNodesRecursive(JTree tree, TreePath path, TreeStatistics stats) {
        if (path == null) {
            return;
        }
        
        stats.incrementTotalNodes();
        
        Object lastComponent = path.getLastPathComponent();
        if (lastComponent instanceof javax.swing.tree.TreeNode) {
            javax.swing.tree.TreeNode node = (javax.swing.tree.TreeNode) lastComponent;
            
            if (node.getChildCount() > 0) {
                stats.incrementExpandedNodes();
                for (int i = 0; i < node.getChildCount(); i++) {
                    TreePath childPath = path.pathByAddingChild(node.getChildAt(i));
                    countNodesRecursive(tree, childPath, stats);
                }
            } else {
                stats.incrementLeafNodes();
            }
        }
    }
    
    // ==================== 内部类 ====================
    
    /**
     * 树统计信息类
     */
    public static class TreeStatistics {
        private int totalNodes = 0;
        private int expandedNodes = 0;
        private int leafNodes = 0;
        
        public void incrementTotalNodes() { totalNodes++; }
        public void incrementExpandedNodes() { expandedNodes++; }
        public void incrementLeafNodes() { leafNodes++; }
        
        public int getTotalNodes() { return totalNodes; }
        public int getExpandedNodes() { return expandedNodes; }
        public int getLeafNodes() { return leafNodes; }
        
        @Override
        public String toString() {
            return String.format("总节点: %d, 展开节点: %d, 叶节点: %d", 
                    totalNodes, expandedNodes, leafNodes);
        }
    }
}
